﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2021-2025 LiLong                                              **
**  This file is part of CommonUnits.                                           **
**                                                                              **
**  CommonUnits is free software: you can redistribute it and/or modify         **
**  it under the terms of the GNU Lesser General Public License as published by **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  CommonUnits is distributed in the hope that it will be useful,              **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU Lesser General Public License for more details.                         **
**                                                                              **
**  You should have received a copy of the GNU Lesser General Public License    **
**  along with CommonUnits.  If not, see <https://www.gnu.org/licenses/>.       **
**********************************************************************************/
#pragma once

#include "../CommonUnits.h"
#include "../UnitLists.h"

namespace CU
{
inline namespace Distance
{
namespace Units
{
using m            = StandardUnit<"m">;
using km           = DeriveUnit<m, "km", std::kilo>;
using Mm           = DeriveUnit<m, "Mm", std::mega>;
using Gm           = DeriveUnit<m, "Gm", std::giga>;
using Tm           = DeriveUnit<m, "Tm", std::tera>;
using Pm           = DeriveUnit<m, "Pm", std::peta>;
using Em           = DeriveUnit<m, "Em", std::exa>;
using dm           = DeriveUnit<m, "dm", std::deci>;
using cm           = DeriveUnit<m, "cm", std::centi>;
using mm           = DeriveUnit<m, "mm", std::milli>;
using um           = DeriveUnit<m, "μm", std::micro>;
using nm           = DeriveUnit<m, "nm", std::nano>;
using pm           = DeriveUnit<m, "pm", std::pico>;
using fm           = DeriveUnit<m, "fm", std::femto>;
using am           = DeriveUnit<m, "am", std::atto>;
using DistanceList = UnitLists<am, fm, pm, nm, um, mm, cm, dm, m, km, Mm, Gm, Tm, Pm, Em>;
} // namespace Units

using Meter      = CommonUnits<double, Units::m>;
using Kilometer  = CommonUnits<double, Units::km>;
using Megameter  = CommonUnits<double, Units::Mm>;
using Gigameter  = CommonUnits<double, Units::Gm>;
using Terameter  = CommonUnits<double, Units::Tm>;
using Petameter  = CommonUnits<double, Units::Pm>;
using Exameter   = CommonUnits<double, Units::Em>;
using Decimeter  = CommonUnits<double, Units::dm>;
using Centimeter = CommonUnits<double, Units::cm>;
using Millimeter = CommonUnits<double, Units::mm>;
using Micrometer = CommonUnits<double, Units::um>;
using Micron     = Micrometer;
using Mikron     = Micrometer;
using Nanometer  = CommonUnits<double, Units::nm>;
using Picometer  = CommonUnits<double, Units::pm>;
using Femtometer = CommonUnits<double, Units::fm>;
using Attometer  = CommonUnits<double, Units::am>;
namespace Literals
{
constexpr auto operator""_m(long double val) { return Meter(val); }
constexpr auto operator""_km(long double val) { return Kilometer(val); }
constexpr auto operator""_Mm(long double val) { return Megameter(val); }
constexpr auto operator""_Gm(long double val) { return Gigameter(val); }
constexpr auto operator""_Tm(long double val) { return Terameter(val); }
constexpr auto operator""_Pm(long double val) { return Petameter(val); }
constexpr auto operator""_Em(long double val) { return Exameter(val); }
constexpr auto operator""_dm(long double val) { return Decimeter(val); }
constexpr auto operator""_cm(long double val) { return Centimeter(val); }
constexpr auto operator""_mm(long double val) { return Millimeter(val); }
constexpr auto operator""_um(long double val) { return Micrometer(val); }
constexpr auto operator""_nm(long double val) { return Nanometer(val); }
constexpr auto operator""_pm(long double val) { return Picometer(val); }
constexpr auto operator""_fm(long double val) { return Femtometer(val); }
constexpr auto operator""_am(long double val) { return Attometer(val); }
} // namespace Literals

template<typename Unit>
inline auto toUnit(double value, const std::string& dest) -> Unit
{
    return toUnitHelper<Unit, Units::DistanceList>(value, dest);
}
} // namespace Distance
} // namespace CU